package com.ronz.stack;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Stack;

/**
 * @Description 栈：使用后缀表达式实现逆波兰计算器。这里直接给出了后缀表达式，中缀表达式到后缀表达式的转换
 *              将在 No4 中演示。
 *              例如: (3+4)× 5-6 对应的后缀表达式就是 3 4 + 5 × 6 - , 针对此后缀表达式求值
 * @Author Ronz
 * @Date 2020/12/29 16:09
 * @Version 1.0
 */
public class No3_Stack_PostfixExpression {
    public static void main(String[] args) {
        // 这里直接给出了后缀表达式
        String express = "3 4 + 5 * 6 -";
        // 1. 将表达式中的数字和符号存储到list集合，方便后面使用
        ArrayList<String> list = getList(express);
        int res = calculate(list);
        System.out.println("result = " + res);
    }


    /**
     * @Description 把后缀表达式中的元素都添加到一个 List 集合中，以便于后面的操作
     * @Param [express]
     */
    private static ArrayList<String> getList(String express){
        String[] strings = express.split(" ");
        return new ArrayList<>(Arrays.asList(strings));
    }

    /**
     * @Description 根据 List 集合中的后缀表达式中的元素计算结果
     */
    private static int calculate(ArrayList<String> list){
        Stack<Integer> stack = new Stack<>();
        int res;

        for (String item : list){
            // 如果这个元素是一个或者多个数字
            if (item.matches("\\d+")){
                // 那就直接入栈
                stack.push(Integer.parseInt(item));
            }else{
                // 如果这个元素是符号，那就要出栈两个数字
                Integer num_1 = stack.pop();
                Integer num_2 = stack.pop();
                // 判断是什么符号
                switch (item){
                    case "+":
                        res = num_1 + num_2;
                        stack.push(res);
                        break;
                    case "-":
                        res = num_2 - num_1;
                        stack.push(res);
                        break;
                    case "*":
                        res = num_1 * num_2;
                        stack.push(res);
                        break;
                    case "/":
                        res = num_2 / num_1;
                        stack.push(res);
                        break;
                        default:
                            break;
                }
            }
        }
        return stack.pop();
    }
}
